home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbdatabs / refcount.h < prev    next >
C/C++ Source or Header  |  1999-03-14  |  7KB  |  177 lines

  1. // ------------------------------- //
  2. // -------- Start of File -------- //
  3. // ------------------------------- //
  4. // ----------------------------------------------------------- //
  5. // C++ Header File Name: refcount.h 
  6. // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
  7. // Produced By: Doug Gaer   
  8. // File Creation Date: 02/03/1997  
  9. // Date Last Modified: 03/15/1999
  10. // Copyright (c) 1997 Douglas M. Gaer
  11. // ----------------------------------------------------------- // 
  12. // ---------- Include File Description and Details  ---------- // 
  13. // ----------------------------------------------------------- // 
  14. /*
  15. The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
  16. All those who put this code or its derivatives in a commercial
  17. product MUST mention this copyright in their documentation for
  18. users of the products in which this code or its derivative
  19. classes are used. Otherwise, you have the freedom to redistribute
  20. verbatim copies of this source code, adapt it to your specific
  21. needs, or improve the code and release your improvements to the
  22. public provided that the modified files carry prominent notices
  23. stating that you changed the files and the date of any change.
  24.  
  25. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
  26. THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
  27. IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
  28. YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
  29. CORRECTION.
  30.  
  31. Reference counting is a technique used to ensure the safe
  32. deletion or modification of an object when a copy of the
  33. object exists. In order to create reference counted objects,
  34. a class must inherit the CountedObject class to embed a
  35. reference count into each object. The RefCount class is used
  36. to handle pointers to reference counted objects. It works by
  37. storing pointers to objects in containers, rather than the
  38. objects themselves. 
  39. */
  40. // ----------------------------------------------------------- //   
  41. #ifndef __REFCOUNT_HPP__
  42. #define __REFCOUNT_HPP__
  43.  
  44. // Reference (C)ounted (O)bject Class
  45. // Reference counting works by storing a refcount with each object.
  46. // Each time the object is referenced by some other object or array
  47. // the counter is incremented. When the entity is finished with the
  48. // object the counter is decremented. When the counter goes to zero,
  49. // it means that no entities are referencing the object, so it can
  50. // be saftly deleted. 
  51. class CountedObject
  52. // Inherit this class to embed a reference count into each object
  53. {
  54. public:
  55.   CountedObject() { refcount = 1; }
  56.   virtual ~CountedObject() { } // Destructor provided for virtuality
  57.  
  58. public:
  59.   void IncRefCount() { refcount++; }
  60.   void DecRefCount() { refcount--; }
  61.   int UnReferenced() { return refcount == 0; } // Return true if not referenced
  62.   unsigned Count() { return refcount; }  // Returns object's refcount
  63.   void Release() { refcount = 0; } // Resets the object's refcount
  64.   
  65. protected:
  66.   unsigned refcount;
  67. };
  68.  
  69. // NOTE: To avoid portability problems with template classes, enable
  70. // the __NOT_USING_TEMPLATE_CLASS__ macro and directly code this
  71. // class for the data type that needs to be reference counted.
  72.  
  73. // Default to using template class
  74. #ifndef __NOT_USING_TEMPLATE_CLASS__
  75. #define __USING_TEMPLATE_CLASS__
  76. #endif
  77.  
  78. #ifdef __USING_TEMPLATE_CLASS__
  79. // (R)eference (C)ount class
  80. // The RefCount class is used to handle reference-counted objects.
  81. // Reference counted pointers work like normal pointers, except
  82. // they keep track of the number of references to the objects they
  83. // point to. To set up a reference counted pointer to an object,
  84. // allocate and initialize the object on the heap using the new
  85. // operator, and then pass a pointer to the object in a call to
  86. // the RefCount constructor.
  87. template<class TYPE>
  88. class RefCount
  89. {
  90. public:
  91.   RefCount(TYPE *ptr = 0) { ObjectPtr = ptr; }
  92.   ~RefCount() { Unbind(); }
  93.   RefCount(const RefCount<TYPE> &ptr) { // Copy constructor
  94.     // Called when a RefCount pointer is passed by value or copied.
  95.     // Like normal pointers only the ObjectPtr is copied, not the
  96.     // object pointed to by ObjectPtr. The aliasing that ocurrs at
  97.     // this point is recorded by incrementing the reference count.
  98.     Bind(ptr);
  99.   }
  100.     
  101.   void operator=(const RefCount<TYPE> &ptr) {
  102.     // Assignment operator using share semantics.
  103.     // This assignment operator does not allow chain assignments
  104.     NewBinding(ptr);
  105.   }
  106.   
  107.   // int is a dummy parameter used to set the pointer to a NULL
  108.   void operator=(int) { Unbind(); ObjectPtr = 0; }
  109.  
  110. protected:
  111.   void Bind(const RefCount<TYPE> &ptr);
  112.   void Unbind();
  113.   void NewBinding(const RefCount<TYPE> &ptr);
  114.  
  115. protected:
  116.   // TYPE assumed to be a structure having IncRefCount(), DecRefCount(),
  117.   // and Referenced() member functions inherited from the CountedObject
  118.   // class.
  119.   TYPE *ObjectPtr;
  120.  
  121. public:
  122.   // The overloaded * and -> operators allow reference counted pointers 
  123.   // to be de-referenced like ordinary pointers.
  124.   TYPE &operator*() const { return *ObjectPtr; } 
  125.   TYPE *operator->() const { return ObjectPtr; }
  126.  
  127.   // Used to test whether a RefCount is null
  128.   int operator!() { return ObjectPtr == 0; } // Return true if equal 0
  129.   operator int() { return ObjectPtr != 0; }  // Return true if not equal 0
  130.   
  131.   friend int operator==(const RefCount<TYPE> &a, const RefCount<TYPE> &b)
  132.   {
  133.     return a.ObjectPtr == b.ObjectPtr;
  134.   }
  135.   
  136.   friend int operator!=(const RefCount<TYPE> &a, const RefCount<TYPE> &b)
  137.   {
  138.     return a.ObjectPtr != b.ObjectPtr;
  139.   }
  140. };
  141.  
  142. template<class TYPE>
  143. void RefCount<TYPE>::Bind(const RefCount<TYPE> &ptr)
  144. // Binds object to the same object that ptr is bound to.
  145. {
  146.   ObjectPtr = ptr.ObjectPtr;
  147.   if (ObjectPtr) ObjectPtr->IncRefCount();
  148. }
  149.  
  150. template<class TYPE>
  151. void RefCount<TYPE>::Unbind()
  152. {
  153.   // Ensure that ObjectPtr is pointing to an object
  154.   if(ObjectPtr == 0) return; 
  155.  
  156.   ObjectPtr->DecRefCount();
  157.   if (ObjectPtr->UnReferenced()) delete ObjectPtr;
  158. }
  159.  
  160. template<class TYPE>
  161. void RefCount<TYPE>::NewBinding(const RefCount<TYPE> &ptr)
  162. // Gives the reference counted pointer a new binding (the same as ptr)
  163. {
  164.   if (ObjectPtr != ptr.ObjectPtr) { // Prevents accidental deletion
  165.     Unbind();
  166.     Bind(ptr);
  167.   }
  168. }
  169.  
  170. #endif // __USING_TEMPLATE_CLASS__
  171.  
  172. #endif // __REFCOUNT_HPP__
  173. // ----------------------------------------------------------- //
  174. // ------------------------------- //
  175. // --------- End of File --------- //
  176. // ------------------------------- //
  177.